# coding=utf-8
"""
"""
import tkinter as tk
import time
import threading
import random
import chess
import PIL as pl
import sys
from PIL import ImageGrab as IG
from ChessDQN import ChessDQN
import numpy as np
import time

from win32 import win32api, win32gui, win32print
from win32.lib import win32con

from win32.win32api import GetSystemMetrics

init_chess = [0, 0, 0, 0, 0, 0, 0, 0, 0]  # 原始棋盘
the_chess = [0, 0, 0, 0, 0, 0, 0, 0, 0]  # 记录棋盘
pre_chess = [0, 0, 0, 0, 0, 0, 0, 0, 0]
show_chess = ''
flag = True
who = 1
count_x = 0
count_y = 0
count_z = 0

top = tk.Tk()
top.title('井字棋 -> Fighting')
top.geometry("300x300")
top.resizable()
show_str = tk.StringVar(top)
tips = tk.StringVar(top)  # 提示信息

# 初始化棋盘信息
ch = []
for i in range(9):
    ch.append(tk.StringVar(top))

# 初始化提示信息
tips.set("")

frame_top = tk.Frame(top)
frame_cont = tk.Frame(top)
frame_bot = tk.Frame(top)
frame_cont1 = tk.Frame(frame_cont)
frame_cont2 = tk.Frame(frame_cont)
frame_cont3 = tk.Frame(frame_cont)

label1 = tk.Label(frame_cont, justify=tk.CENTER, textvariable=show_str, font=("幼圆", 30))

# 棋盘显示label 0~9
l0 = tk.Label(frame_cont1, textvariable=ch[0], font=("幼圆", 30), padx=0)
l1 = tk.Label(frame_cont1, textvariable=ch[1], font=("幼圆", 30), padx=0)
l2 = tk.Label(frame_cont1, textvariable=ch[2], font=("幼圆", 30), padx=0)

l3 = tk.Label(frame_cont2, textvariable=ch[3], font=("幼圆", 30), padx=0)
l4 = tk.Label(frame_cont2, textvariable=ch[4], font=("幼圆", 30), padx=0)
l5 = tk.Label(frame_cont2, textvariable=ch[5], font=("幼圆", 30), padx=0)

l6 = tk.Label(frame_cont3, textvariable=ch[6], font=("幼圆", 30), padx=0)
l7 = tk.Label(frame_cont3, textvariable=ch[7], font=("幼圆", 30), padx=0)
l8 = tk.Label(frame_cont3, textvariable=ch[8], font=("幼圆", 30), padx=0)

label_bottom = tk.Label(frame_bot, justify=tk.CENTER, textvariable=tips, font=("幼圆", 20), padx=0)

chessDQN = ChessDQN()

def get_cur_scle():
    if sys.platform.startswith('win32'):
        """获取真实的分辨率"""
        hDC = win32gui.GetDC(0)
        # 横向分辨率
        # real_w = win32print.GetDeviceCaps(hDC, win32con.DESKTOPHORZRES)
        # 纵向分辨率
        real_h = win32print.GetDeviceCaps(hDC, win32con.DESKTOPVERTRES)

        # logit_w = GetSystemMetrics(0)
        logit_h = GetSystemMetrics(1)

        return round(real_h / logit_h, 2)
    else:
        return 2

def grab_cur_chess(chess_ui, scale = 2):
    # 强制更新UI
    # chess_ui.update()

    # 截图
    grab_pos = (frame_cont.winfo_rootx() + 1, frame_cont.winfo_rooty() + 1,
                frame_cont.winfo_width() + frame_cont.winfo_rootx() - 1,
                frame_cont.winfo_height() + frame_cont.winfo_rooty() - 1)

    if grab_pos[2] > grab_pos[0] and grab_pos[2] > grab_pos[1]:
        pic = IG.grab([scale * pos for pos in grab_pos])
        pic.save("./data/cur_chess.bmp")

def get_cur_chess(scale = 2):
    # 截图
    grab_pos = (frame_cont.winfo_rootx() + 1, frame_cont.winfo_rooty() + 1,
                frame_cont.winfo_width() + frame_cont.winfo_rootx() - 1,
                frame_cont.winfo_height() + frame_cont.winfo_rooty() - 1)

    if grab_pos[2] > grab_pos[0] and grab_pos[3] > grab_pos[1]:
        pic = IG.grab([scale * pos for pos in grab_pos])

    return np.array(pic)

def update_chess():
    """
    更新棋盘
    """
    for i in range(9):
        if the_chess[i] == 1:
            ch[i].set('|X|')
        elif the_chess[i] == -1:
            ch[i].set('|O|')
        else:
            ch[i].set('| |')
        # print(i)

    grab_cur_chess(top, get_cur_scle())

def update_cur_chess(cur_chess):
    """
    更新棋盘
    """
    for i in range(9):
        if cur_chess[i] == 1:
            ch[i].set('|X|')
        elif cur_chess[i] == -1:
            ch[i].set('|O|')
        else:
            ch[i].set('| |')
        # print(i)

def init_ch():
    """
    初始化棋盘
    """
    for i in range(9):
        the_chess[i] = init_chess[i]
    update_chess()
    return the_chess


def ai_go_first():
    if chess.count_zero(the_chess) == 9:
        the_chess[random.randint(0, 8)] = -1
    update_chess()
    forget()


ai_go_fir_b = tk.Button(frame_cont, text='机器先下', command=ai_go_first)


def forget():
    ai_go_fir_b.pack_forget()


def but1():
    """
    人机对战
    """
    flag = True
    init_ch()
    tips.set("人机对战模式")
    l0.bind("<Button-1>", touch_l0)
    l1.bind("<Button-1>", touch_l1)
    l2.bind("<Button-1>", touch_l2)
    l3.bind("<Button-1>", touch_l3)
    l4.bind("<Button-1>", touch_l4)
    l5.bind("<Button-1>", touch_l5)
    l6.bind("<Button-1>", touch_l6)
    l7.bind("<Button-1>", touch_l7)
    l8.bind("<Button-1>", touch_l8)
    ai_go_fir_b.pack(side=tk.TOP)


def run(i, id, pos_infos):
    """
    创建一个机器对打局
    i 表示当前是第几轮下棋
    id表示当前是哪个ai先下
    """
    # new_chess表示当前下棋的棋盘
    new_chess = init_chess[:]
    global count_x
    global count_y
    global count_z
    # 随机下棋
    if id == 1:
        new_chess[random.randint(0, 8)] = -1
    else:
        new_chess[random.randint(0, 8)] = 1

    cur_chess_pos = new_chess[:]
    reward = 1
    is_done = 0
    cur_chess_img = get_cur_chess(get_cur_scle())
    pos_infos.append((cur_chess_img, reward, is_done, cur_chess_pos))
    # 因为井字棋只有9格，所以十步之内必出结果
    for x in range(10):
        # 如果棋盘依旧还剩格子未下
        cur_chess_pos = init_chess[:]
        update_cur_chess(new_chess)
        # update_chess()
        top.update()
        time.sleep(1)
        if chess.count_zero(new_chess) > 0:
            # print(chess.count_zero(new_chess))
            # 当前id ai下棋
            if id == 1:
                # 如果当前是id 1 ai下棋
                # print('*****')
                # print(chess.get_next_x(new_chess,id))
                # 获取下一个下棋位置
                pos = chess.get_next_x(new_chess, id)
                if pos != -1:
                    # 如果下一个下棋不为-1那么直接下棋
                    # todo 这里可以直接记录下棋的位置
                    new_chess[int(chess.get_next_x(new_chess, id))] = id
                    cur_chess_pos[int(chess.get_next_x(new_chess, id))] = 1
                else:
                    # 如果找不到下棋的位置，那就随意找一个空格位下棋
                    # todo 这里可以记录下棋的位置
                    for xx in range(9):
                        if new_chess[xx] == 0:
                            new_chess[xx] = id
                            cur_chess_pos[xx] = 1
            else:
                pos = chess.get_next_o(new_chess, id)
                if pos != -1:
                    # 如果找不到下棋的位置，那就随意找一个空格位下棋
                    # todo 这里可以记录下棋的位置
                    new_chess[int(chess.get_next_o(new_chess, id))] = id
                    cur_chess_pos[int(chess.get_next_o(new_chess, id))] = id
                else:
                    # 如果找不到下棋的位置，那就随意找一个空格位下棋
                    # todo 这里可以记录下棋的位置
                    for xx in range(9):
                        if new_chess[xx] == 0:
                            new_chess[xx] = id
                            cur_chess_pos[xx] = id

            # 切换id ai下棋
            id = id * -1
            # 判断是否结束
            # todo 这里可以记录结束
            reward = 1
            is_done = 0
            if chess.is_win(new_chess, id) == id:
                name = ''
                reward = 10
                is_done = 10
                if id == 1:
                    name = 'X'
                    update_chess()
                    print("第 {} 局 ： {} 赢了！".format(i + 1, name) + ' ' + str(new_chess))
                    tips.set("第 {} 局 ： {} 赢了！".format(i + 1, name))
                    threading.Lock()
                    count_x = count_x + 1
                    threading.RLock()
                    time.sleep(3)
                    break
                else:
                    name = 'O'
                    update_chess()
                    print("第 {} 局 ： {} 赢了！".format(i + 1, name) + ' ' + str(new_chess))
                    tips.set("第 {} 局 ： {} 赢了！".format(i + 1, name))
                    threading.Lock()
                    count_y = count_y + 1
                    threading.RLock()
                    time.sleep(3)
                    break
            elif chess.is_win(new_chess, id * -1) == id * -1:
                id = id * -1
                name = ''
                reward = -10
                is_done = -1
                if id == 1:
                    name = 'X'
                    print("第 {} 局 ： {} 赢了！".format(i + 1, name) + ' ' + str(new_chess))
                    tips.set("第 {} 局 ： {} 赢了！".format(i + 1, name))
                    threading.Lock()
                    count_x = count_x + 1
                    threading.RLock()
                    break
                else:
                    name = 'O'
                    print("第 {} 局 ： {} 赢了！".format(i + 1, name) + ' ' + str(new_chess))
                    tips.set("第 {} 局 ： {} 赢了！".format(i + 1, name))
                    threading.Lock()
                    count_y = count_y + 1
                    threading.RLock()
                    break
            elif chess.count_zero(new_chess) == 0:
                is_done = 1
                print("第 {} 局 ： 平局".format(i + 1) + ' ' + str(new_chess))
                tips.set("第 {} 局 ： 平局".format(i + 1))
                threading.Lock()
                count_z = count_z + 1
                threading.RLock()
                break
            else:
                pass

            # todo 这里可以组织本次下棋的位置信息
            cur_chess_img = get_cur_chess(get_cur_scle())

            pos_infos.append((cur_chess_img, reward, is_done, cur_chess_pos))
        else:
            # 否则和棋
            # is_done = 0
            # reward = 1
            print("第 {} 局 ： 平局".format(i + 1) + ' ' + str(new_chess))
            tips.set("第 {} 局 ： 平局".format(i + 1))
            threading.Lock()
            count_z = count_z + 1
            threading.RLock()

            # cur_chess_img = get_cur_chess(get_cur_scle())
            break
    # print(str(i + 1) + ' ' + str(new_chess))
    '''if i == 9:
        print("第 {} 局 ： 平局".format(i+1) + ' ' + str(new_chess))
        tips.set("第 {} 局 ： 平局".format(i+1))
        threading.Lock()
        count_z = count_z + 1
        threading.RLock()'''
    # 这里仅仅只是更新棋盘 并无其他问题
    time.sleep(3)
    for i in range(9):
        the_chess[i] = new_chess[i]
    update_chess()
    # threading.Lock()
    tips.set("50局已经结束！\nX 共赢 {}次\nO 共赢 {}次\n平局 {} 次".format(count_x, count_y, count_z))
    # threading.RLock()


def but2():
    """
    机器对战
    """
    print(" ")
    ai_go_fir_b.pack_forget()
    flag = False
    global count_x
    global count_y
    global count_z
    count_x = 0
    count_y = 0
    count_z = 0
    tips.set("机器对战模式")
    l0.unbind("<Button-1>")
    l1.unbind("<Button-1>")
    l2.unbind("<Button-1>")
    l3.unbind("<Button-1>")
    l4.unbind("<Button-1>")
    l5.unbind("<Button-1>")
    l6.unbind("<Button-1>")
    l7.unbind("<Button-1>")
    l8.unbind("<Button-1>")
    id = 1

    for j in range(500):
        # th = []
        pos_infos = []
        for i in range(1):
            init_ch()
            id = id * -1
            run(i, id, pos_infos)
            # try:
            # run(i, id, pos_infos)
            #     th.append(threading.Thread(target=run, args=(i, id, pos_infos)))
            #     th[i].start()
            #     th = threading.Thread(target=run, args=(i, id, pos_infos))
                # th.start()
                # th.join()
            # except Exception as e:
            #     print(e)
            #     i = i - 1

        # for thi in th:
        #     thi.join()

        chessDQN.network_learn(pos_infos)
    # tips.set("50 局已经结束！ X 共赢 {}次， O 共赢 {}次， 平局 {} 次".format(count_x,count_y,count_z))


def ai_go(w):
    """
    机器走棋 O
    """

    if chess.count_zero(the_chess) < 9:
        po = chess.is_danger(the_chess, 1)
        if po != -1:
            the_chess[po] = w
            update_chess()
        elif constraint(w) == False:
            pass
        else:
            the_chess[chess.get_next_o(the_chess, -1)] = w
            update_chess()
        if chess.is_win(the_chess, -1) == -1:
            tips.set("你输了！")
    if chess.count_zero(the_chess) == 0:
        tips.set("平局！")

def constraint(w):
    """
    判断是否处于危险状态
    """
    po = chess.is_danger(the_chess, -1)
    if po != -1:
        the_chess[po] = w
        update_chess()
        return False
    return True


def peo_go(po):
    """
    获取人们按键，并下棋
    """
    if the_chess[po] == 0:
        pre_chess = the_chess.copy()
        the_chess[po] = who
        update_chess()
        if chess.is_win(the_chess, who) == who:
            tips.set('你赢了！')
        elif chess.count_zero(the_chess) == 0:
            tips.set("平局！")
        else:
            ai_go(who * -1)


def touch_l0(e):
    peo_go(0)


def touch_l1(e):
    peo_go(1)


def touch_l2(e):
    peo_go(2)


def touch_l3(e):
    peo_go(3)


def touch_l4(e):
    peo_go(4)


def touch_l5(e):
    peo_go(5)


def touch_l6(e):
    peo_go(6)


def touch_l7(e):
    peo_go(7)


def touch_l8(e):
    peo_go(8)


tk.Button(frame_top, text='人机对决', command=but1).pack(side=tk.LEFT)
tk.Button(frame_top, text='机器对决', command=but2).pack(side=tk.RIGHT)

update_chess()

l0.pack(side=tk.LEFT)
l1.pack(side=tk.LEFT)
l2.pack(side=tk.LEFT)
l3.pack(side=tk.LEFT)
l4.pack(side=tk.LEFT)
l5.pack(side=tk.LEFT)
l6.pack(side=tk.LEFT)
l7.pack(side=tk.LEFT)
l8.pack(side=tk.LEFT)

label_bottom.pack()

frame_cont1.pack()
frame_cont2.pack()
frame_cont3.pack()

frame_top.pack()
frame_cont.pack()
top.mainloop()
frame_bot.pack()

top.mainloop()